using LitJson;
using System;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Text;

namespace BToolkit
{
    public class LicenceChecker : MonoBehaviour
    {
        private const string publicKey =
            @"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyroeJpu1M5byXqSblSAz
/G1G42CTEwJkRzkddZdrgxeXdZa8SEJqYBDnlI4XtXDlWmBmCuxGiUwpzqTSrr2P
3by9ij8bjbo8tCHFx+zM8nX1LNbiqW0KwmWKGxnIM4isKlhQQeNSAlVV0FvQNuJu
F3dhY7vbOBdLNaXq+zhPthAsvgZwfsWX1fHxbm9RtYP9z26KfFJJ6tpFepeWBxED
xVP9eLL0xnbUYmyaEwZ0NcCVb8I2OT5EG1QMRBi0/KBv6ET2QAcChvoeWm+pW7D2
w0O4AL+vEKmBebiyHMX5OtsAKoOhE/b+fbaYlq9XQDPJcDsvGoBFZumphq0nsC6I
kwIDAQAB
-----END PUBLIC KEY-----";

        private static LicenceChecker _instance;
        public static LicenceChecker Instance
        {
            get
            {
                if (!_instance)
                {
                    _instance = GameObject.FindObjectOfType<LicenceChecker>();
                    if (!_instance)
                    {
                        GameObject go = new GameObject("LicenceChecker");
                        DontDestroyOnLoad(go);
                        _instance = go.AddComponent<LicenceChecker>();
                    }
                }
                return _instance;
            }
        }
        private string fileDir
        {
            get
            {
                if (Application.platform == RuntimePlatform.Android)
                {
                    return $"/storage/emulated/0/Android";
                }
                return $"{Application.persistentDataPath}/Licence/{SystemInfo.GetDeviceID()}";
            }
        }
        private string fileName = "time";
        private string licenceFileName = "lic";
        private int timeInFile;
        private Transform popupDialogParent;
        private Action onActiveSuccess;
        private const int RequestCode = 1;
        private bool hasRegister;

        public void CheckLicence(Transform popupDialogParent, Action onActiveSuccess)
        {
            if (!hasRegister)
            {
                MainActivity.Instance.RegisterActivityResult(OnActivityResult);
                MainActivity.Instance.RegisterPermissionResult(OnPermissionResult);
                hasRegister = true;
            }
            this.popupDialogParent = popupDialogParent;
            this.onActiveSuccess = onActiveSuccess;
            bool success = SaveOrRefreshSysTime();
            Debug.Log($"SaveOrRefreshSysTime: {success}");
            if (!success)
            {
                DialogTip.Show("应用需要存储权限", 0, null, () =>
                {
                    SDCardPermission.RequestSDCardPermission(RequestCode);
                });
                return;
            }
            if (TimeUtils.DateTimeToTimestamp(DateTime.Now) >= timeInFile)
            {
                string cacheLicence = GetStorageLicence();
                Debug.Log($"cacheLicence:{cacheLicence}");
                if (!string.IsNullOrEmpty(cacheLicence))
                {
                    string licenceInfo = RSAUtils.PublicKeyDecrypt(cacheLicence, publicKey);
                    Debug.Log($"licenceInfo:{licenceInfo}");
                    if (!string.IsNullOrEmpty(licenceInfo))
                    {
                        JsonData data = JsonMapper.ToObject(licenceInfo);
                        string deviceId = (string)data["deviceId"];
                        bool isDeviceMatch = deviceId.Equals(SystemInfo.GetDeviceID());
                        Debug.Log($"isDeviceMatch:{isDeviceMatch}");
                        if (deviceId.Equals(SystemInfo.GetDeviceID()))
                        {
                            int year = (int)data["year"];
                            int month = (int)data["month"];
                            int day = (int)data["day"];
                            bool isTimeout = DateTime.Now.AddDays(-1) > new DateTime(year, month, day);
                            Debug.Log($"isTimeout:{isTimeout}");
                            if (!isTimeout)
                            {
                                PanelActivation.Dispose();
                                onActiveSuccess?.Invoke();
                                return;
                            }
                        }
                    }
                }
            }
            PanelActivation.Show(popupDialogParent);
        }

        private void OnActivityResult(int requestCode, int resultCode)
        {
            bool isGeted = SDCardPermission.HavePermission();
            Debug.Log($"OnActivityResult:{requestCode} {resultCode} {isGeted}");
            if (requestCode == RequestCode && isGeted)
            {
                PanelActivation.Show(popupDialogParent);
            }
        }

        private void OnPermissionResult(int requestCode, string permission, bool isGeted)
        {
            Debug.Log($"OnPermissionResult:{requestCode} {permission} {isGeted}");
            if (requestCode == RequestCode && isGeted)
            {
                PanelActivation.Show(popupDialogParent);
            }
        }

        private bool SaveOrRefreshSysTime()
        {
            try
            {
                if (!Directory.Exists(fileDir)) Directory.CreateDirectory(fileDir);
                if (File.Exists($"{fileDir}/{fileName}"))
                {
                    string content = File.ReadAllText($"{fileDir}/{fileName}");
                    timeInFile = int.Parse(content);
                    //文件存在且仍小于系统时间，说明系统时间没被改，则覆盖最新的时间进去
                    if (TimeUtils.DateTimeToTimestamp(DateTime.Now) >= timeInFile)
                    {
                        timeInFile = TimeUtils.DateTimeToTimestamp(DateTime.Now);
                        File.WriteAllText($"{fileDir}/{fileName}", timeInFile.ToString());
                    }
                }
                else
                {
                    //文件不存在，直接保存当前系统时间
                    timeInFile = TimeUtils.DateTimeToTimestamp(DateTime.Now);
                    File.WriteAllText($"{fileDir}/{fileName}", timeInFile.ToString());
                }
                return true;
            }
            catch (UnauthorizedAccessException ex)
            {
                Debug.LogError(ex);
                return false;
            }
        }

        public void Activation(string licence)
        {
            if (TimeUtils.DateTimeToTimestamp(DateTime.Now) < timeInFile)
            {
                DialogTip.Show("激活失败\n请校准系统时间");
                return;
            }

            string licenceInfo = RSAUtils.PublicKeyDecrypt(licence, publicKey);
            if (string.IsNullOrEmpty(licenceInfo))
            {
                DialogTip.Show("激活失败");
                return;
            }
            JsonData data = JsonMapper.ToObject(licenceInfo);
            string deviceId = (string)data["deviceId"];
            int year = (int)data["year"];
            int month = (int)data["month"];
            int day = (int)data["day"];
            if (DateTime.Now.AddDays(-1) > new DateTime(year, month, day))
            {
                DialogTip.Show("激活码已过期");
                return;
            }
            Debug.Log($"deviceId:{deviceId} = {SystemInfo.GetDeviceID()}");
            if (!deviceId.Equals(SystemInfo.GetDeviceID()))
            {
                DialogTip.Show("该激活码并非用于本设备");
                return;
            }
            SaveLicence(licence);
            SaveOrRefreshSysTime();
            PanelActivation.Dispose();
            onActiveSuccess?.Invoke();
            DialogTip.Show("激活成功");
        }

        private void SaveLicence(string licence)
        {
            try
            {
                if (!Directory.Exists(fileDir)) Directory.CreateDirectory(fileDir);
                File.WriteAllText($"{fileDir}/{licenceFileName}", licence, Encoding.UTF8);
            }
            catch (UnauthorizedAccessException ex)
            {
                Debug.LogError(ex);
            }
        }

        private string GetStorageLicence()
        {
            string fullPath = $"{fileDir}/{licenceFileName}";
            if (File.Exists(fullPath))
            {
                return File.ReadAllText(fullPath);
            }
            return null;
        }

        private void Update()
        {
            if (Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.LeftControl))
            {
                if (Input.GetKeyDown(KeyCode.R))
                {
                    PanelActivation.Show(popupDialogParent);
                }
            }
        }
    }
}